﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml.Data;

namespace G.Data
{
    /// <summary>
    /// Utility class for implementing incremental loading.  Just subclass, and implement
    /// PullDataAsync().  Don't forget to use the async keyword!
    /// </summary>
    /// <typeparam name="T">Type of item in collection</typeparam>
    public abstract class IncrementalLoadingCollection<T>
        : ObservableCollection<T>, ISupportIncrementalLoading, INotifyPropertyChanged, IDisposable
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public event EventHandler<IsLoadingDataChangedEventArgs> IsLoadingDataChanged;

        /// <summary>
        /// 向侦听器通知已更改了某个属性值。
        /// </summary>
        /// <param name="propertyName">用于通知侦听器的属性的名称。此
        /// 值是可选的，可以在从支持
        /// <see cref="CallerMemberNameAttribute"/> 的编译器调用时自动提供。</param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
            {
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private uint _totalItemsCount = 0;
        private bool _hasMoreItems = true;
        private bool _isLoadingData = false;

        public IncrementalLoadingCollection()
        {
        }

        private int pageNum = 0;

        public int PageNum
        {
            get
            {
                return pageNum;
            }
            set
            {
                if (pageNum != value)
                {
                    pageNum = value;
                    OnPropertyChanged();
                }
            }
        }

        private int pageSize = 20;
        /// <summary>
        /// 默认20条数据
        /// </summary>
        public int PageSize
        {
            get
            {
                return pageSize;
            }
            set
            {
                if (pageSize != value)
                {
                    pageSize = value;
                    OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Total number of items of the collection; it's not the number of loaded items.
        /// </summary>
        public uint TotalItemsCount
        {
            get
            {
                return _totalItemsCount;
            }
            set
            {
                if (_totalItemsCount != value)
                {
                    _totalItemsCount = value;

                    OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Gets/sets whether the collection should continue loading data from source.        
        /// </summary>
        public bool HasMoreItems
        {
            get
            {
                return _hasMoreItems;
            }
            set
            {
                _hasMoreItems = value;
            }
        }

        /// <summary>
        /// IsLoadingData is true when data is actually being pulled (usually over a network).
        /// Useful with progress bars/rings.
        /// </summary>
        public bool IsLoadingData
        {
            get
            {
                return _isLoadingData;
            }
            set
            {
                if (_isLoadingData != value)
                {
                    bool oldValue = _isLoadingData;
                    bool newValue = value;
                    _isLoadingData = newValue;
                    OnPropertyChanged();
                    if (IsLoadingDataChanged != null)
                    {
                        IsLoadingDataChanged(this, new IsLoadingDataChangedEventArgs(oldValue, newValue));
                    }
                }
            }
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public void AddRange(IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                this.Add(item);
            }
        }

        public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
        {
            return new IncrementalLoader<T>(this, count);
        }

        /// <summary>        
        /// PullDataAsync is where you actually get items from a data source (web service, database, XML, etc.)
        /// When implementing this method, make sure you make it async.
        /// </summary>
        /// <param name="currentPageLowerBound">Current page lower bound.</param>
        /// <param name="currentPageUpperBound">Current page upper bound.</param>
        /// <returns></returns>
        public abstract Task<IncrementalLoadingResult<T>> PullDataAsync(int pageNo, int PageSize);

        public abstract void Dispose();

        /// <summary>
        /// 刷新
        /// </summary>
        public void Refresh()
        {
           this.PageNum = 0;
            this.HasMoreItems = true;
            while (this.Count > 0)
                this.RemoveAt(0);
        }
    }
}